#include "rtp/FeedbackPs.h"
#include "rtp/Packet.h"
#include "rtp/FeedbackItem.h"
#include "rtp/FeedbackPsFir.h"

#include <memory>

namespace Rtp {
    namespace Rtcp {
        template<typename Item>
        FeedbackPsItemsPacket<Item>* FeedbackPsItemsPacket<Item>::Parse(const uint8_t* data, size_t len) {
            if (len < Packet::CommonHeaderSize + FeedbackPacket::HeaderSize) {
                return nullptr;
            }

            auto *commonHeader = const_cast<CommonHeader*>(reinterpret_cast<const CommonHeader*>(data));
            
            std::unique_ptr<FeedbackPsItemsPacket<Item>> packet(new FeedbackPsItemsPacket<Item>(commonHeader));

            size_t offset = Packet::CommonHeaderSize + FeedbackPacket::HeaderSize;

            while (len > offset) {
                auto* item = FeedbackItem::Parse<Item>(data + offset, len - offset);

                if (item) {
                    if (!item->IsCorrect()) {
                        delete item;
                        break;
                    }
                    packet->AddItem(item);
                    offset += item->GetSize();
                } else {
                    break;
                }
            }
            return packet.release();
        }

        template<typename Item>
        size_t FeedbackPsItemsPacket<Item>::Serialize(uint8_t* buffer) {
            size_t offset = FeedbackPacket::Serialize(buffer);
            for (auto *item : this->items) {
                offset += item->Serialize(buffer + offset);
            }
            return offset;
        }

        template<typename Item>
        void FeedbackPsItemsPacket<Item>::Dump() const {
            for (auto *item : this->items) {
                item->Dump();
            }
        }

        template class FeedbackPsItemsPacket<FeedbackPsFirItem>;
    }
}